package com.ht.WeNas.rest_controller;

import cn.hutool.core.util.StrUtil;
import com.ht.WeNas.config.WeNasCustom;
import com.ht.WeNas.data.dto.UserDto;
import com.ht.WeNas.data.entity.User;
import com.ht.WeNas.data.enumObj.UserType;
import com.ht.WeNas.data.vo.Res;
import com.ht.WeNas.data.vo.user.ChangePwdForm;
import com.ht.WeNas.data.vo.user.ChangeUserTypeFrom;
import com.ht.WeNas.data.vo.user.CreateUserForm;
import com.ht.WeNas.data.vo.user.UserLoginForm;
import com.ht.WeNas.service.UserService;
import com.ht.WeNas.utils.ThreadLocalUtil;
import com.ht.WeNas.utils.TokenUtil;
import com.ht.WeNas.utils.exceptions.UserNotLoginException;
import com.ht.WeNas.utils.tag.PublicApi;
import com.ht.WeNas.utils.tag.RequireUserType;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.*;

@Tag(name = "用户控制器")
@RestController
@RequestMapping("/api/user")
public class UserController {
    private final UserService userService;
    private final WeNasCustom weNasCustom;

    public UserController(UserService userService, WeNasCustom weNasCustom) {
        this.userService = userService;
        this.weNasCustom = weNasCustom;
    }
    
    @PublicApi
    @Operation(summary = "登录")
    @PostMapping("/login")
    public Res<Void> login(@RequestBody UserLoginForm userLoginForm, HttpServletResponse response) {
        String token = userService.login(userLoginForm);
        this.addTokenToResponse(token, response);
        if (StrUtil.isNotBlank(token)) {
            return Res.ok();
        } else {
            return Res.fail("登录失败，用户名或密码错误");
        }
    }
    
    @Operation(summary = "创建用户")
    @PostMapping("/create")
    public Res<UserDto> createUser(@RequestBody CreateUserForm createUserForm, HttpServletResponse response) {
        UserDto userDto = userService.createUser(createUserForm);
        this.addTokenToResponse(TokenUtil.createToken(userDto), response);
        if (userDto == null) {
            return Res.fail("创建用户失败，请检查后重试");
        }
        return Res.ok(userDto);
    }

    @PublicApi
    @Operation(summary = "登出")
    @GetMapping("/logout")
    public Res<String> logout(HttpServletResponse response) {
        response.addCookie(new Cookie("token", null));
        return Res.ok();
    }
    
    @Operation(summary = "获取当前登录的用户")
    @GetMapping("/self")
    public Res<UserDto> getSelf() throws UserNotLoginException {
        UserDto userDto = ThreadLocalUtil.getUserDto();
        return Res.ok(userDto);
    }
    
    @Operation(summary = "修改密码")
    @RequireUserType(UserType.User)
    @PostMapping("/pwd")
    public Res<Void> changePwd(@RequestBody ChangePwdForm changePwdForm) throws UserNotLoginException {
        UserDto userDto = ThreadLocalUtil.getUserDto();
        userService.changePassword(userDto, changePwdForm.getOldPwd(), changePwdForm.getNewPwd());
        return Res.ok();
    }
    
    @Operation(summary = "修改用户类型")
    @RequireUserType(UserType.Admin)
    @PostMapping("/type")
    public Res<Void> changeUserType(@RequestBody ChangeUserTypeFrom changeUserTypeFrom) {
        userService.changeUserType(changeUserTypeFrom.getUserId(), changeUserTypeFrom.getUserType());
        return Res.ok();
    }
    
    @Operation(summary = "删除用户", description = "删除用户，非管理员只能删除自身")
    @RequireUserType(UserType.User)
    @DeleteMapping("/delete/{id}")
    public Res<Void> deleteUser(@PathVariable("id") long id) throws UserNotLoginException {
        userService.deleteUser(id);
        return Res.ok();
    }
    
    @Operation(summary = "通过id获取用户信息")
    @GetMapping("/info/{id}")
    public Res<UserDto> getUserById(@PathVariable("id") long id) {
        User user = userService.getUserById(id);
        UserDto userDto = new UserDto(user);
        return Res.ok(userDto);
    }
    
    private void addTokenToResponse(String token, HttpServletResponse response) {
        Cookie cookie = new Cookie("token", token);
        cookie.setMaxAge(weNasCustom.getTokenExpireSeconds());
        cookie.setHttpOnly(true);
        cookie.setPath("/");
        response.addCookie(cookie);
    }
}
